package com.yhy.wxzn.wcs.device.rgv;

import com.yhy.wxzn.common.utils.SpringUtil;
import com.yhy.wxzn.common.utils.WcsUtils;
import com.yhy.wxzn.wcs.device.plc.bean.FourCarPlc;
import com.yhy.wxzn.wcs.device.rgv.bean.FourWayRgv;
import com.yhy.wxzn.wcs.device.rgv.core.plc.ToRgv;
import com.yhy.wxzn.wcs.device.rgv.enums.RgvStatus;
import com.yhy.wxzn.wcs.device.rgv.exception.AvoidInterceptedException;
import com.yhy.wxzn.wcs.entity.WcsTask;
import com.yhy.wxzn.wcs.enums.TaskStatus;
import com.yhy.wxzn.wcs.enums.TaskType;
import com.yhy.wxzn.wcs.service.impl.WcsTaskServiceImpl;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FourWayRgvTaskExecuteThread extends RgvTaskExecuteThread {
    public static final ThreadLocal<FourWayRgv> RGV_THREAD_LOCAL = new ThreadLocal();
    public static final ThreadLocal<FourCarPlc> RGV_PLC_THREAD_LOCAL = new ThreadLocal();
    private FourWayRgv rgv;
    private FourCarPlc fourCarPlc;

    private WcsTaskServiceImpl taskService = SpringUtil.getBean(WcsTaskServiceImpl.class);


    public FourWayRgvTaskExecuteThread(FourWayRgv fourWayRgv){
        super(fourWayRgv.getDeviceInfo().getDeviceName()+"四向车任务线程");
        this.rgv = fourWayRgv;
        this.fourCarPlc = fourWayRgv.getFourCarPlc();
    }




    private void process(){

        if (!checkRgvStatus()) return;

        if (!checkGroundCode()) return;

        /**
         * 要加上小车的状态字段，任务状态这些要加上取消。
         */
        WcsTask task = taskService.getFirstCanExecuteTask(rgv.getDeviceInfo().getId());
        if (!checkTask(task)) return;

        if (!checkCharge(task)) return;

        try {
            initRgvData(task);
            new FourWayTaskHandler(task).handleTask();
        }catch (AvoidInterceptedException e) {
            log.info(e.getMessage(),e);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            taskService.updateTaskStatus(task,TaskStatus.ERROR);
            rgv.setRgvStatus(RgvStatus.ERROR);
        }finally {
            clearRgvData();
        }
    }

    private void clearRgvData() {
        rgv.getCurLocationAndRefreshRgvLocation();

        rgv.setCurTask(null);
    }

    private void initRgvData(WcsTask task) {
        rgv.setIntercepted(false);
        rgv.setCurTask(task);
    }

    private boolean checkTask(WcsTask task) {
        if (task == null) return false;
        if (task.getTaskStatus().equals(TaskStatus.ERROR)) return false;

        return true;
    }

    private boolean checkGroundCode() {

        try {
            rgv.getCurLocation();
        } catch (Exception e) {
            return false;
        }

        return true;
    }



    private boolean checkCharge(WcsTask task){

        if (task.getTaskType() != TaskType.CHARGE && fourCarPlc.getDcdl() < 10){
            log.error(rgv.getDeviceInfo().getDeviceName() + "电池电量不足，无法执行任务");
            return false;
        }

        //正在充电，结束充电
        if (fourCarPlc.getCdzt() == 1) {
            ToRgv.getInstance(rgv).stopCharge();
            while (fourCarPlc.getCdzt() == 1){
                log.info(rgv.getDeviceInfo().getDeviceName() + "等待小车结束充电");
                WcsUtils.sleep(1000);
                rgv.checkIntercept("等待小车结束充电");
            }
        }

        return true;
    }

    /**
     * 检查rgv能否满足执行任务的条件
     */
    private boolean checkRgvStatus() {

        if (fourCarPlc.getCarStatus() == 0){
            log.error(rgv.getDeviceInfo().getDeviceName() + "正在工作中");
            return false;
        }

        if (rgv.getRgvStatus() != RgvStatus.READY){
            log.error(rgv.getDeviceInfo().getDeviceName() + "状态未就绪");
            return false;
        }

        try {
            rgv.checkIntercept("checkRgvStatus");
        } catch (Exception e) {
           rgv.setRgvStatus(RgvStatus.ERROR);
           return false;
        }


        if (fourCarPlc.getErrorType() != 0){
            log.error("来源PLC："+rgv.getDeviceInfo().getDeviceName() + fourCarPlc.getErrorMessage());
            return false;
        }

        return true;
    }


    @Override
    public void run() {
        initThreadLocal();
        while (true){
            try {
                WcsUtils.sleep(1000);
                process();
            }catch (Exception e){
                log.error(e.getMessage(),e);
            }
        }
    }

    private void initThreadLocal() {
        RGV_THREAD_LOCAL.set(this.rgv);
        RGV_PLC_THREAD_LOCAL.set(this.rgv.getFourCarPlc());
    }


    public FourCarPlc getFourCarPlc() {
        return fourCarPlc;
    }
}
